# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

"""
This script implements the `mach devtools-css-db` command. It runs an xpcshell script
that uses inIDOMUtils to query the CSS properties used by the browser. This information
is used to generate the properties-db.js file.
"""

import json
import os
import sys
import string
import subprocess
from mozbuild.base import (
    MozbuildObject,
    MachCommandBase,
)
from mach.decorators import (
    CommandProvider,
    Command,
)

def resolve_path(start, relativePath):
    """Helper to resolve a path from a start, and a relative path"""
    return os.path.normpath(os.path.join(start, relativePath))

def stringify(obj):
    """Helper to stringify to JSON"""
    return json.dumps(obj, sort_keys=True, indent=2, separators=(',', ': '))

@CommandProvider
class MachCommands(MachCommandBase):
    @Command(
        'devtools-css-db', category='post-build',
        description='Rebuild the devtool\'s static css properties database.')
    def generate_css_db(self):
        """Generate the static css properties database for devtools and write it to file."""

        print("Re-generating the css properties database...")
        db = self.get_properties_db_from_xpcshell()

        self.output_template({
            'cssProperties': stringify(db['cssProperties']),
            'pseudoElements': stringify(db['pseudoElements'])})

    def get_properties_db_from_xpcshell(self):
        """Generate the static css properties db for devtools from an xpcshell script."""
        build = MozbuildObject.from_environment()

        # Get the paths
        script_path = resolve_path(self.topsrcdir,
            'devtools/shared/css/generated/generate-properties-db.js')
        gre_path = resolve_path(self.topobjdir, 'dist/bin')
        browser_path = resolve_path(self.topobjdir, 'dist/bin/browser')
        xpcshell_path = build.get_binary_path(what='xpcshell')
        print(browser_path)

        sub_env = dict(os.environ)
        if sys.platform.startswith('linux'):
            sub_env["LD_LIBRARY_PATH"] = gre_path

        # Run the xcpshell script, and set the appdir flag to the browser path so that
        # we have the proper dependencies for requiring the loader.
        contents = subprocess.check_output([xpcshell_path, '-g', gre_path,
                                            '-a', browser_path, script_path],
                                           env = sub_env)
        # Extract just the output between the delimiters as the xpcshell output can
        # have extra output that we don't want.
        contents = contents.split('DEVTOOLS_CSS_DB_DELIMITER')[1]

        return json.loads(contents)

    def output_template(self, substitutions):
        """Output a the properties-db.js from a template."""
        js_template_path = resolve_path(self.topsrcdir,
            'devtools/shared/css/generated/properties-db.js.in')
        destination_path = resolve_path(self.topsrcdir,
            'devtools/shared/css/generated/properties-db.js')

        with open(js_template_path, 'rb') as handle:
            js_template = handle.read()

        preamble = '/* THIS IS AN AUTOGENERATED FILE.  DO NOT EDIT */\n\n'
        contents = string.Template(js_template).substitute(substitutions)

        with open(destination_path, 'wb') as destination:
            destination.write(preamble + contents)

        print('The database was successfully generated at ' + destination_path)
